//
//  GCDBlockTableViewController.m
//  GCDDemo
//
//  Created by 苏沫离 on 2018/8/6.
//  Copyright © 2018年 苏沫离. All rights reserved.
//


#define CellIdentifer @"UITableViewCell"

#import "GCDBlockTableViewController.h"

@interface GCDBlockTableViewController ()
@property (nonatomic ,strong) NSArray<NSString *> *titleArray;

@end

@implementation GCDBlockTableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifer];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.titleArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifer forIndexPath:indexPath];
    cell.textLabel.text = self.titleArray[indexPath.row];
    cell.textLabel.numberOfLines = 0;
    return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    NSLog(@"-------- 开始处理 --------");
    
    if (indexPath.row == 0)
    {
        [self dispatch_block_perform_Method];
    }
    else if (indexPath.row == 1)
    {
        [self dispatch_block_wait_Method];
    }
    else if (indexPath.row == 2)
    {
        [self dispatch_block_notify_Method];
    }
    else if (indexPath.row == 3)
    {
        [self dispatch_block_cancel_Method];
    }
    NSLog(@"-------- 结束处理 --------");

}

#pragma mark - 任务操作(取消、暂停/恢复)
/*
 //暂停、恢复队列上的任务
 //dispatch_suspend并不会立即暂停正在运行的block，而是在当前block执行完成后，暂停后续的block执行。
 void dispatch_suspend(dispatch_object_t object);
 void dispatch_resume(dispatch_object_t object);
 void dispatch_cancel(void *object);
 
 
 long dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);//该函数会阻塞当前线程进行等待
 void dispatch_block_cancel(dispatch_block_t block);
 void dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue, dispatch_block_t notification_block);
 */

#pragma mark 任务执行操作

- (void)dispatch_block_perform_Method
{
    dispatch_block_t taskA = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
        NSLog(@"开始执行taskA === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskA === %@",NSThread.currentThread);
    });
    
    dispatch_block_perform(DISPATCH_BLOCK_DETACHED, taskA);
}

/*

 */

#pragma mark 任务等待操作

/*
 有时我们需要等待特定的 block 执行完成之后，再去执行其他任务。有两种方法可以获取到指定 block 执行结束的时机。
 long dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);//该函数会阻塞当前线程进行等待
 void dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue, dispatch_block_t notification_block);
 
 
 该函数会阻塞当前线程进行等待。传入需要设置的 block 和等待时间 timeout。timeout 参数表示函数在等待 block 执行完毕时，应该等待多久。如果执行 block 所需的时间小于 timeout，则返回 0，否则返回非 0 值。此参数也可以取常量 DISPATCH_TIME_FOREVER，这表示函数会一直等待 block 执行完，而不会超时。可以使用 dispatch_time 函数和 DISPATCH_TIME_NOW 常量来方便的设置具体的超时时间。
 
 */
- (void)dispatch_block_wait_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_CONCURRENT);

    dispatch_block_t taskA = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
        NSLog(@"开始执行taskA === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskA === %@",NSThread.currentThread);
    });
    
    dispatch_block_t taskB = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
        NSLog(@"开始执行taskB === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskB === %@",NSThread.currentThread);
    });
    
    dispatch_block_t taskC = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
        NSLog(@"开始执行taskC === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskC === %@",NSThread.currentThread);
    });
    
    dispatch_async(queue, taskA);
    NSLog(@"执行 dispatch_block_wait");
    long  value = dispatch_block_wait(taskA, dispatch_time(DISPATCH_TIME_NOW,  (int64_t)(6 * NSEC_PER_SEC)));
    NSLog(@"dispatch_block_wait === %ld",value);
    if (value == 0)
    {
        NSLog(@"执行成功");
        dispatch_async(queue, taskB);
    }
    else
    {
        NSLog(@"执行超时");
        dispatch_async(queue, taskC);
    }
}


- (void)dispatch_block_notify_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_block_t taskA = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
        NSLog(@"开始执行taskA === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskA === %@",NSThread.currentThread);
    });
    
    dispatch_block_t taskB = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
        NSLog(@"开始执行taskB === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskB === %@",NSThread.currentThread);
    });
    
    dispatch_block_notify(taskA, queue, taskB);
    dispatch_async(queue, taskA);
}



#pragma mark 任务取消操作

- (void)dispatch_block_cancel_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_block_t taskA = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
        NSLog(@"开始执行taskA === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskA === %@",NSThread.currentThread);
    });
    
    dispatch_block_t taskB = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
        NSLog(@"开始执行taskB === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:2];//模拟耗时任务
        NSLog(@"结束执行taskB === %@",NSThread.currentThread);
    });

    dispatch_async(queue, taskA);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        dispatch_block_cancel(taskA);
    });
    dispatch_block_cancel(taskB);
    dispatch_async(queue, taskB);
}


#pragma mark - setter and getter

- (NSArray<NSString *> *)titleArray
{
    if (_titleArray == nil)
    {
        _titleArray = @[@"dispatch_block_perform",
                        @"dispatch_block_wait",
                        @"dispatch_block_notify",
                        @"dispatch_block_cancel"];
    }
    return _titleArray;
}


@end
